package com.atguigu.gmall.item.service.impl;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.feignclients.product.SkuFeignClient;
import com.atguigu.mall.cache.annotation.MallCache;
import com.atguigu.mall.cache.service.CacheService;
import com.atguigu.gmall.product.entity.SkuImage;
import com.atguigu.gmall.product.entity.SpuSaleAttr;
import com.atguigu.gmall.item.vo.CategoryView;
import com.atguigu.gmall.product.entity.SkuInfo;

import com.atguigu.gmall.item.service.SkuDetailService;
import com.atguigu.gmall.item.vo.SkuDetailVo;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName SkuDetailServiceImpl
 * @Description TODO
 * @Author king
 * @Date 2022/11/7 18:15
 * @Version 1.0
 */
@Service
@Slf4j
public class SkuDetailServiceImpl implements SkuDetailService {

    @Autowired
    SkuFeignClient skuFeignClient;

    @Autowired
    CacheService cacheService;

    @Autowired
    RedissonClient redissonClient;

    /**
     * 缓存穿透：  随机值穿透公鸡
     * 缓存击穿
     * 缓存雪崩
     * @param skuId
     * @return
     */

    @MallCache(
            cacheKEY = RedisConst.SKU_INFO_CACHE_KEY + "#{#args[0]}",
            bitmapIndex = "#{#args[0]}",
            bitmapKey = RedisConst.SKUID_BITMAP_KEY,
            ttl = 7,
            unit = TimeUnit.DAYS
    )  //以后专注业务逻辑
    //自定义设置注解属性------专注业务逻辑 ---sku:info:58
    @Override
    public SkuDetailVo getDetail(Long skuId){
        return getDetailVoFromRpc(skuId);
    }

//    public SkuDetailVo getDetailWithRedisson(Long skuId){
//
//        String cacheKey = RedisConst.SKU_INFO_CACHE_KEY + skuId;
//
//        //String cacheKey = "sku:info:" + skuId; //58~20000
//        //1,先去缓存中查询商品
//        SkuDetailVo cacheDate = cacheService.getCacheData(cacheKey);
//
//
//        //使用bitmap进行占位
//        if (cacheDate == null){
//            log.info("[{}] 商品, 缓存未命中,准备回源",skuId);
//            //使用bitmap--------若使用布隆过滤器则有可能产生误判
//            boolean flag = cacheService.existSkuIdByBitMap(skuId);
//            //Lock lock = new ReentrantLock();
//
//            String lockKey = RedisConst.LOCK_PREFIX + cacheKey;
//            RLock lock = redissonClient.getLock(lockKey);
//
//            //百万请求并发同时进来,只有一个tryLock
//            boolean b = lock.tryLock();
//            if (flag){
//                try {
//                    log.info("[{}] 商品, 位图判定有,查询中",skuId);
//                    SkuDetailVo vo = null;
//
//                    //2.bitmap中有,数据库有,缓存没有
//                    //回源操作
//                    vo = getDetailVoFromRpc(skuId);
//                    //保存到缓存，无条件保存： null值缓存；解决一般缓存穿透问题
//                    cacheService.saveCacheData(cacheKey,vo);
//                    return vo;
//                } finally {
//                    lock.unlock();
//                }
//            } else {
//                try {
//                    Thread.sleep(500);
//                    return cacheDate = cacheService.getCacheData(cacheKey);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                } finally {
//
//                }
//            }
//
//            log.info("[{}] 商品, 位图判定没有,有隐藏公鸡危险,直接返回null",skuId);
//            //3,bitmap中没有,直接返回null
//            return null;
//        }
//
//        log.info("[{}] 商品, 缓存命中,直接返回",skuId);
//
//        return cacheDate;
//
//    }


    public SkuDetailVo getDetailVoFromRpc(Long skuId) {

        //1,sku的基本信息
        SkuDetailVo vo = new SkuDetailVo();
        //基本信息
        SkuInfo skuInfo = skuFeignClient.getSkuInfo(skuId).getData();
        //商品图片
        List<SkuImage> skuImages = skuFeignClient.getSkuImages(skuId).getData();
        skuInfo.setSkuImageList(skuImages);

        //2,sku所在的完整分类
        CategoryView categoryView = skuFeignClient.getSkuCategoryView(skuInfo.getCategory3Id()).getData();
        vo.setCategoryView(categoryView);

        //3,sku的基本分类
        vo.setSkuInfo(skuInfo);

        //4,sku对应的spu定义的所有销售属性列表
        List<SpuSaleAttr> spuSaleAttrs = skuFeignClient.getSpuSaleAttr(skuInfo.getSpuId(),skuId).getData();
        vo.setSpuSaleAttrList(spuSaleAttrs);

        //sku各种组合的json
        String data = skuFeignClient.getSkuValueJson(skuInfo.getSpuId()).getData();
        vo.setValuesSkuJson(data);

        //商品价格
        Result<BigDecimal> skuPrice = skuFeignClient.getSkuPrice(skuId);
        vo.setPrice(skuPrice.getData());

        return vo;
    }
}
